﻿namespace com.crownpack.convert
{
    using System;
    using System.Reflection;

    using com.crownpack.common;
    using com.crownpack.Extensions.AssemblyExtensions;
    using com.crownpack.Extensions.StringExtensions;

    public class ConvertInitiatives : CommandLineBase
    {
        #region Fields

        string _ParentCustomerNo;
        string _SourceUri;
        string _TargetList;
        string _TargetUri;

        #endregion Fields

        #region Enumerations

        enum Keyword
        {
            ParentCustomerNo,
            SourceUri,
            TargetList,
            TargetUri
        }

        #endregion Enumerations

        #region Properties

        string ParentCustomerNo
        {
            get
            {
                if ( string.IsNullOrEmpty( _ParentCustomerNo ) )
                {
                    var a = GetCommandArgument( Keyword.ParentCustomerNo );
                    if ( a != null )
                        _ParentCustomerNo = a.Value;
                }
                return _ParentCustomerNo;
            }
        }

        string SourceUri
        {
            get
            {
                if ( string.IsNullOrEmpty( _SourceUri ) )
                {
                    var a = GetCommandArgument( Keyword.SourceUri );
                    if ( a != null )
                        _SourceUri = a.Value;
                }
                return _SourceUri;
            }
        }

        string TargetList
        {
            get
            {
                if ( string.IsNullOrEmpty( _TargetList ) )
                {
                    var a = GetCommandArgument( Keyword.TargetList );
                    if ( a != null )
                        _TargetList = a.Value;
                }
                return _TargetList;
            }
        }

        string TargetUri
        {
            get
            {
                if ( string.IsNullOrEmpty( _TargetUri ) )
                {
                    var a = GetCommandArgument( Keyword.TargetUri );
                    if ( a != null )
                        _TargetUri = a.Value;
                }
                return _TargetUri;
            }
        }

        #endregion Properties

        #region Methods

        public override void DisplayHelp( )
        {
            string s = Assembly.GetExecutingAssembly( ).GetManifestResourceAsString( "Help.txt" );
            base.DisplayHelp( s.Replace( "<%=commandname%>", CommandName ) );
        }

        public override void Execute( )
        {
            Convert convert = new Convert
            {
                ParentCustomerNumber = ParentCustomerNo.ToInt32( ),
                SourceUri = new Uri( SourceUri ),
                TargetList = TargetList,
                TargetUri = new Uri( TargetUri )
            };
            convert.ItemsConverted += new EventHandler<Convert.ItemsConvertedEventArgs>( reportItemsAdded );
            convert.SynchronizationStarted += new EventHandler( synchronizationStarted );
            DisplayStatusMessage( "Conversion started..." );
            ExitCode = convert.Execute( );
            if ( ExitCode == EXITCODE_SUCCESS )
                AddCompletionMessage( "Conversion completed successfully." );
        }

        public override void Initialize( )
        {
            AddArgument( Keyword.ParentCustomerNo, true, "-c" );
            AddArgument( Keyword.SourceUri, true, "-e" );
            AddArgument( Keyword.TargetList, true, "-l" );
            AddArgument( Keyword.TargetUri, true, "-t" );
        }

        public override void InitializeDefaults( )
        {
            base.InitializeDefaults( );
        }

        public override void ParseForKeywords( string[ ] args )
        {
            for ( int i = 0; i < args.Length; i++ )
            {
                string arg = args[ i ];
                i++;
                string value = i < args.Length ? args[ i ] : string.Empty;
                CommandArgument c;
                if ( IsArgument( arg, c = GetCommandArgument( Keyword.ParentCustomerNo ) ) )
                {
                    if ( c.IsValueSet )
                        AddArgumentAlreadySpecifiedErrorMessage( arg );
                    else
                        SetCommandArgumentValue( Keyword.ParentCustomerNo, value );
                }
                else if ( IsArgument( arg, c = GetCommandArgument( Keyword.SourceUri ) ) )
                {
                    if ( c.IsValueSet )
                        AddArgumentAlreadySpecifiedErrorMessage( arg );
                    else
                        SetCommandArgumentValue( Keyword.SourceUri, value );
                }
                else if ( IsArgument( arg, c = GetCommandArgument( Keyword.TargetList ) ) )
                {
                    if ( c.IsValueSet )
                        AddArgumentAlreadySpecifiedErrorMessage( arg );
                    else
                        SetCommandArgumentValue( Keyword.TargetList, value );
                }
                else if ( IsArgument( arg, c = GetCommandArgument( Keyword.TargetUri ) ) )
                {
                    if ( c.IsValueSet )
                        AddArgumentAlreadySpecifiedErrorMessage( arg );
                    else
                        SetCommandArgumentValue( Keyword.TargetUri, value );
                }
                else
                    AddErrorMessage( "Unkown argument '{0}' with the value of '{1}'.", arg, value );
            }
        }

        public override bool Validate( )
        {
            bool ok = true;

            Uri sourceUri = null;
            if ( string.IsNullOrEmpty( SourceUri ) )
            {
                ok = false;
                AddErrorMessage( "Export file Url was not specified." );
                ExitCode = Convert.ExitCode.ExportFileNotFound;
            }
            else
            {
                try
                {
                    sourceUri = new Uri( SourceUri );
                }
                catch
                {
                    ok = false;
                    AddErrorMessage( "Export file Url not valid." );
                    ExitCode = Convert.ExitCode.ExportFileNotFound;
                }
            }

            Uri targetUri = null;
            if ( string.IsNullOrEmpty( TargetUri ) )
            {
                ok = false;
                AddErrorMessage( "Target Url was not specified." );
                ExitCode = Convert.ExitCode.TargetSiteUrlNotFound;
            }
            else
            {
                try
                {
                    targetUri = new Uri( TargetUri );
                }
                catch
                {
                    ok = false;
                    AddErrorMessage( "Target Url not valid." );
                    ExitCode = Convert.ExitCode.TargetSiteUrlNotFound;
                }
            }

            if ( sourceUri != null )
            {
                if ( !Convert.DoesExportFileExists( sourceUri ) )
                {
                    ok = false;
                    AddErrorMessage( "The export file was not found at {0}.", sourceUri );
                    ExitCode = Convert.ExitCode.ExportFileNotFound;
                }
            }

            if ( targetUri != null )
            {
                if ( !Convert.DoesTargetListExists( targetUri, TargetList ) )
                {
                    ok = false;
                    AddErrorMessage( "The target list '{0}' was not found at {1}.", TargetList, targetUri );
                    ExitCode = Convert.ExitCode.TargetListNotFound;
                }

                string clientSiteUrl = Convert.GetClientSiteUrl( targetUri );

                if ( !Convert.DoesConfigurationExists( targetUri ) )
                {
                    ok = false;
                    AddErrorMessage( "The configuration for {0} was not found.", clientSiteUrl );
                    ExitCode = Convert.ExitCode.ConfigurationNotFound;
                }
                else if ( !Convert.IsConfigurationActive( targetUri ) )
                {
                    ok = false;
                    AddErrorMessage( "The configuration for {0} was found, but it is not active.", clientSiteUrl );
                    ExitCode = Convert.ExitCode.ConfigurationNotActive;
                }

                if ( string.IsNullOrEmpty( ParentCustomerNo ) || !Convert.IsParentCustomerNoValid( targetUri, ParentCustomerNo.ToInt32( ) ) )
                {
                    ok = false;
                    AddErrorMessage( "Customer number is not valid. It is different than what is configured for {0}.", clientSiteUrl );
                    ExitCode = Convert.ExitCode.ParentCustomerNoInvalid;
                }
            }

            if ( ok )
                ExitCode = EXITCODE_SUCCESS;
            else if ( ExitCode == 0 )
                ExitCode = EXITCODE_ERROR;

            return ok;
        }

        static void Main( string[ ] args )
        {
            ConvertInitiatives o = new ConvertInitiatives( );
            o.Process( args );
            Environment.ExitCode = o.ExitCode;
            o = null;

            //Convert convert = new Convert
            //{
            //    ParentCustomerNumber = 920006,
            //    //SourceUri = new Uri( "http://win-pv542842fga:8888/sites/cpwf/export/2012-10-29_11.34.06_full.tsv" ),
            //    SourceUri = new Uri( "http://win-pv542842fga:8888/sites/cpwf/export/2012-10-30_16.04.24_eatonfull.tsv" ),
            //    TargetList = "initiatives",
            //    TargetUri = new Uri( "http://win-pv542842fga:8888/sites/cpwf/client/i2e/Lists/initiatives" )
            //};
            //convert.Execute( );
        }

        void reportItemsAdded( object sender, Convert.ItemsConvertedEventArgs e )
        {
            DisplayStatusMessage( "Total of {0} items converted.", e.NumberItems );
        }

        void synchronizationStarted( object sender, EventArgs e )
        {
            DisplayStatusMessage( "Final synchronization started. One moment..." );
        }

        #endregion Methods
    }
}